/*******************************************************************************
 * Witz - Winboard Chess Engine                                                *
 * DEBUG.H                                                                     *
 *                                                                             *
 * This file is not required to compile the program but it may prove useful    *
 * debugging functions.                                                        *
 *                                                                             *
 * Please refer to the licence notice in MAIN.C                                *
 *                                                                             *
 * Copywright (C) 2006 Pradu Kannan                                            *
 * http://witz.sf.net/                                                         *
 ******************************************************************************/

#ifndef __debug
#define __debug

int debugdepth=0;
move DebugMoves[2048];
FILE* debugfile;

/*printBitboard()
 *prints visual representation of the 64 bit number with bit 0 at the bottom
 *left and bit 63 at the top right
 *
 *@param x - a 64 bit number
 */
void printBitBoard(char* s, U64 x)
{
	int i;
	int j;
	printf("%s:\n",s);
	for(i=56;i>=0;i-=8)
	{
		for(j=0;j<8;j++)
		     printf("%d",(x&(toBit[i+j]))!=U64EMPTY);
		printf("\n");
	}
}

/*printAllBoardInfo()
 *prints all the info about the board
 */
void printAllBoardInfo()
{
	//printBoard();
	printf("\n");
	printf("mainboard.fifty\t\t= %d\n",mainboard.fifty);
	printf("mainboard.side\t\t= %s\n",sideToStr[mainboard.side]);
	printf("mainboard.xside\t\t= %s\n",sideToStr[mainboard.xside]);
	printf("mainboard.hashkey\t= 0x%X%X\n",((long int)(mainboard.hashkey)),*(((long int*)&mainboard.hashkey)+1));
	printf("mainboard.material\t= %d\n",mainboard.material);
	if(mainboard.EP)
		printf("mainboard.EP\t\t= %d\n",LastOne(mainboard.EP));
	else
		printf("mainboard.EP\t\t= No EP Square\n");
	printf("mainboard.castling\t= ");
	if(mainboard.castling&WK) //temp=true is intended
		printf("K");
	if(mainboard.castling&WQ)
		printf("Q");
	if(mainboard.castling&BK)
		printf("k");
	if(mainboard.castling&BQ)
		printf("q");
	if(!mainboard.castling)
		printf("No Castling Privilages");
	printf("\n");
	printf("gamedepth\t\t= %d\n",gamedepth);
	printf("compside\t\t= %d\n",compside);
	printf("initialMoveNumber\t= %d\n",initialMoveNumber);
	printBitBoard("mainboard.AllPieces",mainboard.AllPieces);
	printBitBoard("mainboard.PiecesSide[WHITE]",mainboard.PiecesSide[WHITE]);
	printBitBoard("mainboard.PiecesSide[BLACK]",mainboard.PiecesSide[BLACK]);
	printBitBoard("mainboard.L90",mainboard.L90);
	printBitBoard("mainboard.L45",mainboard.L45);
	printBitBoard("mainboard.R45",mainboard.R45);
	printBitBoard("mainboard.Pieces[P]",mainboard.Pieces[P]);
	printBitBoard("mainboard.Pieces[N]",mainboard.Pieces[N]);
	printBitBoard("mainboard.Pieces[B]",mainboard.Pieces[B]);
	printBitBoard("mainboard.Pieces[R]",mainboard.Pieces[R]);
	printBitBoard("mainboard.Pieces[Q]",mainboard.Pieces[Q]);
	printBitBoard("mainboard.Pieces[K]",mainboard.Pieces[K]);
}

/*printBoardDebug()
 */
void printBoardDebug(const board* pos)
{
	char h;
	U64 i,k;
	int a;
	if(!pos->AllPieces)
		puts("\t  \t     Null Board!");
	else if(pos->side==BLACK)
		puts("\t  \t    Black to Move");
	else if(pos->side==WHITE)
		puts("\t  \t    White to Move");
	printf("\t  %c",PB_UL);
	for(a=0;a<8;a++)
		printf("%c%c%c%c",PB_H,PB_H,PB_H,PB_HD);
	printf("\b%c\n",PB_UR);
	for(k=toBit[56];k;k>>=8)
	{
		printf("\t%c %c ",'1'+LastOne(k)/8,PB_V);
		for(i=k;i && ((LastOne(i)&0x38)==LastOne(k));i<<=1)
  		{
			if(i&pos->PiecesSide[BLACK])
				h=PieceToCharLowercase(pos->PieceTypes[LastOne(i)]);
			else if(i&pos->PiecesSide[WHITE])
				h=PieceToCharUppercase(pos->PieceTypes[LastOne(i)]);
			else
			     h=' ';
			printf("%c %c ",h,PB_V);
		}
		printf("\n");
		if(LastOne(k))
		{
			printf("\t  %c",PB_VR);
			for(a=0;a<8;a++)
				printf("%c%c%c%c",PB_H,PB_H,PB_H,PB_CRS);
			printf("\b%c\n",PB_VL);
		}
	}
	printf("\t  %c",PB_LL);
	for(a=0;a<8;a++)
		printf("%c%c%c%c",PB_H,PB_H,PB_H,PB_HU);
	printf("\b%c\n",PB_LR);
	printf("\t   ",PB_LL);
	for(a=0;a<8;a++)
		printf(" %c  ",'a'+a);
	printf("\n");
}

void addDebugMove(move m)
{
	DebugMoves[debugdepth]=m;
	debugdepth++;
}

void removeDebugMove()
{
	if(debugdepth>0)
		debugdepth--;
	else
		printf("error\n");
}

void openDebugFile()
{
	debugfile=fopen("debug.txt","w");
}

void closeDebugFile()
{
	fclose(debugfile);
}

/*moveToString()
 *converts a move to an xboard move string
 *print before making move
 *
 *@param m - the move to be turned into a string
 *
 *@returns m as an xboard string
 */
char* debugMoveToString(move m)
{
	static char str2[15], kingpos;
	if(m==NULLMOVE)
		return "Null";
	if(extractSpecial(m) && extractPiece(m)==K)
	{
		kingpos=(char)LastOne(piecesSide(mainboard,K));
		if(extractSpecial(m)>>1) //if Queenside Castling
		{
			m+=encodeFrom(kingpos)+encodeTo(kingpos-2);
		}
		else
			m+=encodeFrom(kingpos)+encodeTo(kingpos+2);
	}
	sprintf(str2, "%c%c%c%c%c%c%c",
		pieceToStr[extractPiece(m)],
		ColCoord(extractFrom(m)),
		RowCoord(extractFrom(m)),
		extractCapture(m)?'x':'-',
		ColCoord(extractTo(m)),
		RowCoord(extractTo(m)),
		PieceToCharLowercase(extractPromotion(m)));
	return str2;
}

void debugMoveList(moveList ml)
{
	int i;
	for(i=0;i<ml.moveCount;i++)
		printf("%d) %s\n",i,debugMoveToString(ml.moves[i].m));
}

void printPositionToFile(moveList* ml, int alpha, int beta, int score,bool dir)
{
	int i;
	/*if(dir)
	{
		int i;
		for(i=0;i<ml->moveCount;i++)
			fprintf(debugfile,"%s ",debugMoveToString(ml->moves[i].m));
		fprintf(debugfile,"%\n");
	}*/
	fprintf(debugfile,"%d%s ",debugdepth,dir?"++":"--");
	if(alpha==INF)
		fprintf(debugfile,"(INF)");
	else if(alpha==NEGINF)
		fprintf(debugfile,"(-INF)");
	else
		fprintf(debugfile,"(%d)",alpha);
	if(beta==INF)
		fprintf(debugfile,"(INF)");
	else if(beta==NEGINF)
		fprintf(debugfile,"(-INF)");
	else
		fprintf(debugfile,"(%d)",beta);
	if(score==INF)
		fprintf(debugfile,"(INF)");
	else if(score==NEGINF)
		fprintf(debugfile,"(-INF)");
	else
		fprintf(debugfile,"(%d)",score);
	for(i=0;i<debugdepth;i++)
		fprintf(debugfile,"%s ",debugMoveToString(DebugMoves[i]));
	fprintf(debugfile,"\n");
}

#endif
